package hh.util.bean;

import hh.util.Asserts;
import lombok.Data;
import lombok.experimental.Accessors;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

@Data
@Accessors(chain = true)
public abstract class PropertyDesc implements GetAndSet {

    protected String fieldName;
    protected Field field;
    protected Method getter;
    protected Method setter;

    public PropertyDesc(Field field, Method getter, Method setter) {
        this(field);
        if (getter != null)
            Asserts.False(ClassUtil.matchGetter(field, getter), "字段：{} 与getter方法：{} 不匹配", field, getter);
        if (setter != null)
            Asserts.False(ClassUtil.matchSetter(field, setter), "字段：{} 与Setter方法：{} 不匹配", field, setter);
        this.getter = getter;
        this.setter = setter;
    }

    public PropertyDesc(Field field) {
        this.fieldName = field.getName();
        this.field = field;
        this.field.setAccessible(true);
    }

    public Object read(Object obj) {
        try {
            return getter == null ? field.get(obj) : getter.invoke(obj);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

    }

    public void write(Object obj, Object... args) {
        try {
            if (setter != null) setter.invoke(obj, args);
            field.set(obj, args);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }


    public boolean hasSetter() {
        return setter != null;
    }

    public boolean hasGetter() {
        return getter != null;
    }
}
